Most modern computer systems include a central processing unit (CPU) and a main memory. The speed at which the CPU can decode and execute instructions to process data has for some time exceeded the speed at which instructions and operands can be transferred from main memory to the CPU. In an attempt to reduce the problems caused by this mismatch, many computers include a cache memory or buffer between the CPU and main memory.
A cache memory is a small, high-speed buffer memory used to hold temporarily those portions of the contents of main memory which it is believed will be used in the near future by the CPU. The main purpose of a cache memory is to shorten the time necessary to perform memory accesses. The information located in cache memory may be accessed in much less time than that located in main memory. Thus, a CPU with a cache memory needs to spend far less time waiting for instructions and operands to be fetched and/or stored. For example, in typical large, high-speed computers, main memory can be accessed in 300 to 600 nanoseconds; information can be obtained from a cache memory on the other hand, in 50 to 100 nanoseconds. For such machines, the cache memory produces a very substantial increase in execution speed. However, the performance of the computer system is still limited in instruction execution rate by cache memory access time. Additional increases in instruction execution rate can be gained by further decreasing the cache memory access time.
The success of cache memories is based on the assumption that, because a particular memory location has been referenced, that location and locations very close to it are very likely to be accessed in the near future. This is often referred to as the property of locality. The property of locality has two aspects, temporal and spatial. While over short periods of time, a program distributes its memory references nonuniformly over its address space, the portions of the address space which are favored remain largely the same for long periods of time. This first property of locality, called temporal locality, or locality by time, means that the information which will be in use in the near future is likely to be in use already. This type of behavior can be expected from program loops in which both data and instructions are reused. The second property of locality, locality by space, means that portions of the address space which are in use generally consist of a fairly small number of individually contiguous segments of that address space. Locality by space, then, means that the loci of reference of the program in the near future are likely to be near the current loci of reference. This type of behavior can be expected from common knowledge of programs: related data items (variables, arrays) are usually stored together, and instructions are mostly executed sequentially. Since the cache memory buffers segments of information that have been recently used, the property of locality implies that needed information is also likely to be found in the cache. See, Smith, A. J., Cache Memories, ACM Computing Surveys, 14:3 (Sept. 1982), pp 473-530.
A cache is made up of many blocks of one or more words of data, each of which has associated with it an address tag that uniquely identifies which block of main memory it is a copy of. Each time the processor makes a memory reference, the cache makes an address tag comparison to see if it has a copy of the requested data. If it does, it supplies the data; if it does not, it retrieves the block from main memory, replacing one of the blocks stored in the cache, and then supplies the retrieved data to the processor.
Optimizing the design of a cache memory generally has four aspects:
(1) Maximizing the probability of finding a memory reference's information in the cache (the so-called "hit" ratio), PA0 (2) minimizing the time required to access information that is indeed in the cache (access time), PA0 (3) minimizing the delay due to a cache "miss", and PA0 (4) minimizing the overheads of updating main memory and maintaining multicache consistency.
All of these objectives must be accomplished under suitable cost constraints and in view of the interrelationship between the parameters; for example, the trade-off between hit ratio and access time. It is obvious that the larger the cache, the higher the probability of finding the needed information in it. Cache sizes cannot be expanded without limit, however, for several reasons: cost, the most important reason in many machines, especially small ones; physical size, the cache must fit on the boards and in the cabinets; and access time, the larger the cache, the slower it will become.
Information is generally retrieved from cache associatively to determine if there is a "hit". However, large, fully associative memories are both very expensive and somewhat slow. In early cache memories, all the elements were searched associatively for each request by the CPU. In order to provide the access time required to keep up with the CPU, cache size was limited and the hit ratio was thus rather low.
FIG. 1 is a schematic illustration of a conventional, direct-map single-set cache. As described above, the illustrated cache comprises a number of blocks, each with its own data and address tag. For any cache access, a portion of the address, called the index, is used to select one block (in an operation like a RAM access) which will be checked to see if it is the one requested. If it is not the requested block, then the cache will fetch the correct one from main memory, replacing the block it checked. Thus, for any block in main memory, there is exactly one block in the cache that may contain it. The cache illustrated in FIG. 1 has four words of data in each block. Because the location in the cache uniquely specifies the index portion of the address, the tag compare need only be done on the higher portion of the address.
Cache memories may also be organized into groups of smaller associative memories called sets, each containing a number of locations, referred to as the set size. For a cache of size m, divided into L sets, there are s=m/L locations in each set. When an address in main memory is mapped into the cache, it can appear in any of the L sets. For a cache of a given size, searching each of the sets in parallel can improve access time by a factor of L.
FIG. 2 is a schematic illustration of the simplest and most common associative multi-set cache, the two-set cache. In an n-set cache, each block of memory has "n" possible slots in which it might be stored in the cache; so a process could have "n" blocks with the same index in the cache simultaneously without "thrashing". The cache accesses each of the "n" blocks at the specified index simultaneously and checks to see if any is the requested block. If one is, the cache returns it; if it is not, it fetches the requested block from main memory replacing one of the blocks with the new one. In a cache with more than two sets, the extra sets are added in parallel, with the final level of OR-ing and multiplexing getting wider.
The design choice between the single-set, direct-map cache shown in FIG. 1 and an associative, multi-set cache of the type shown in FIG. 2 is based on a trade-off between access time and hit ratio. For the same size cache, the access time for a multi-set cache is longer than for a single-set cache because the associative address comparison and required multiplexing can take a long time. The multi-set cache is also more expensive. On the other hand, the hit ratio of the multi-set cache is better.
Obviously, it would be advantageous to improve the access time for a multi-set cache.